package com.gujiangbo.redemo;

import com.github.javafaker.Faker;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 列表操作
 * |操作类型| 操作
 * |添加   | rpush lpush linsert
 * |查     | lrange lindex llen
 * |删除   | lpop rpop lrem ltrim
 * |修改   | lset
 * |阻塞操作| blpop brpop
 */
public class RedisListDemo {
    public Jedis jedis = JedisFactory.getJedis();

    /**
     * rpush key value [value ....] 从右边插入元素
     */
    @Test
    public void testRpush() {

        jedis.select(5);
        Long rpush = jedis.rpush("alphabet", "a", "b", "c", "d", "e", "f", "g");
        Long names = jedis.rpush("names", "zhangsan", "lisi", "wangwu", "zhaoliu");
        String[] str = new String[100000];
        for (int i = 0; i < 100000; i++) {
            str[i] = "hhh" + i;
        }
        Long objlist = jedis.rpush("objlist", str);
        System.out.println("添加alphabet个数:" + rpush);
        System.out.println("添加names个数:" + names);
        System.out.println("添加objlist个数:" + objlist);

    }

    /**
     * lpush key value [value ....] 从左侧插入元素
     */
    @Test
    public void testLpush() {
        Long lpush = jedis.lpush("city", "Jiangsu", "ShangHai", "Beijing");
        System.out.println("添加元素个数:" + lpush);
        this.print("city");
    }


    @Test
    public void testLpush1() {
        int v = 100;
        Faker faker = new Faker();
        String names[] = new String[100];
        jedis.select(5);
        IntStream.range(0, 100).forEach(item -> {
            names[item] = faker.name().name();
        });
        if (jedis.exists("names")) {
            jedis.del("names");
        }
        jedis.lpush("names", names);
        jedis.close();
    }

    /**
     * linsert key before/after pivot value 向某个元素前或者后插入元素
     */
    @Test
    public void testLinsert() {
        //在字母a之前插入新字母Z
        jedis.linsert("alphabet", BinaryClient.LIST_POSITION.BEFORE, "a", "Z");
        System.out.println("在字母a之前插入新字母Z");
        this.print("alphabet");
    }

    /**
     * lrange 0 -1 命令可以从左到右获取列表的所有元素
     * lrange key start end 获取指定范围内的元素列表
     */
    @Test
    public void testLrange() {
        //this.print("alphabet");
        jedis.select(5);
        List<String> names = jedis.lrange("names", 0, -1);
        List<String> result = names.stream().filter(v -> v.contains("A")).limit(20).map(String::toUpperCase).collect(Collectors.toList());
        result.forEach(System.out::println);
        jedis.close();
    }

    /**
     * lindex key index 获取列表指定索引下标的元素
     */
    @Test
    public void testLindex() {
        String alphabet = jedis.lindex("alphabet", 3);
        System.out.println(alphabet);
    }

    /**
     * llen key 获取列表的长度
     */
    @Test
    public void testLlen() {
        Long alphabet = jedis.llen("alphabet");
        System.out.println("alphabet的长度:" + alphabet);
    }

    /**
     * lpop key 从列表左侧弹出元素
     * rpop key 从列表右侧弹出元素
     */
    @Test
    public void testPop() {
        String alphabet = jedis.lpop("alphabet");
        System.out.println(alphabet);
        String alphabet1 = jedis.rpop("alphabet");
        System.out.println(alphabet1);
    }

    /**
     * lrem key count value 删除指定元素
     * lrem命令会从列表中找到等于value的元素进行删除，根据count的不同分为三种情况：
     * count>0 从左到右，删除最多的count个元素
     * count<0 从右到左，删除最多count绝对值个元素
     * count=0 删除所有
     */
    @Test
    public void testLrem() {
        //删除所有g
        jedis.lrem("alphabet", 0, "g");
        this.print("alphabet");

    }

    /**
     * lset key index value 修改指定索引下标的元素
     */
    @Test
    public void testLset() {
        print("names");
        System.out.println("--------");
        jedis.lset("names", 0, "huangbingsheng");
        print("names");
    }

    @Test
    public void objectEncoding() {

        String objectEncoding = jedis.objectEncoding("objlist");
        System.out.println(objectEncoding);

    }

    public void print(String key) {
        jedis.lrange(key, 0, -1).forEach(System.out::println);
    }

}
